package com.weilx959.spt.app;

import com.weilx959.spt.app.constants.AppConstants;
import com.weilx959.spt.app.context.ConfigContext;
import com.weilx959.spt.app.context.LogThreadContext;
import com.weilx959.spt.app.context.PluginConfigurationContext;
import com.weilx959.spt.app.context.PluginContext;
import com.weilx959.spt.app.controller.MainViewController;
import com.weilx959.spt.app.model.AppConfig;
import com.weilx959.spt.app.utils.ResourceBundleUtil;
import com.weilx959.spt.core.HostServicesContext;
import com.weilx959.spt.core.StageContext;
import com.weilx959.spt.core.component.VDialog;
import com.weilx959.spt.core.constants.CommonConstants;
import com.weilx959.spt.core.utils.FXMLUtil;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.Optional;

/**
 * sql解析器应用程序
 *
 * @author weilx
 * @since 2024-08-31
 */
@Slf4j
public class SqlParserApplication extends Application {

    /**
     * 主要
     *
     * @param args args
     */
    public static void main(String[] args) {
        Application.launch(args);
    }

    /**
     * 开始
     *
     * @param stage 阶段
     * @throws Exception 异常
     */
    @Override
    public void start(Stage stage) throws Exception {
        log.info("hello.");
        initIconImage(stage);
        loadConfig();
        StageContext.set(stage);
        HostServicesContext.set(getHostServices());
        MainViewController controller = FXMLUtil.getController(AppConstants.MAIN_VIEW, ResourceBundleUtil.get());
        Scene scene = new Scene(controller.getRootPane());
        scene.getStylesheets().add(AppConstants.BASE_STYLE_FILE);
        scene.getStylesheets().add(Optional.ofNullable(ConfigContext.get())
            .map(AppConfig::getGeneral)
            .map(AppConfig.General::getTheme)
            .orElse(CommonConstants.DEFAULT_THEME)
            .getStyle());
        stage.initStyle(StageStyle.UNDECORATED);
        stage.setTitle(AppConstants.TITLE);
        stage.setScene(scene);
        stage.setOnCloseRequest(event -> {
            String title = ResourceBundleUtil.get().getString("app.main.exit.message");
            VDialog.confirmBlocked(title, VDialog::close, dialog -> {
                dialog.close();
                event.consume();
                return null;
            });
        });
        stage.show();
    }

    @Override
    public void stop() throws Exception {
        log.info("bye.");
        super.stop();
        Optional.ofNullable(PluginContext.getAll())
            .ifPresent(plugins -> plugins.forEach((id, plugin) -> plugin.getController().onDestroy()));
        // 保存配置到文件
        ConfigContext.save();
        PluginConfigurationContext.save();
    }

    /**
     * 重启应用
     */
    public static void restart() {
        StageContext.get().close();
        LogThreadContext.stop();
        Platform.runLater(() -> {
            try {
                new SqlParserApplication().start(new Stage());
            } catch (Exception e) {
                log.error("Application start error:", e);
            }
        });
    }

    private static void initIconImage(Stage stage) {
        getIconStream()
            .ifPresent(inputStream -> {
                try {
                    Taskbar taskbar = Taskbar.getTaskbar();

                    if (taskbar.isSupported(Taskbar.Feature.ICON_IMAGE)) {
                        taskbar.setIconImage(ImageIO.read(inputStream));
                    } else if (Objects.nonNull(stage)) {
                        stage.getIcons().add(new Image(inputStream));
                    }
                } catch (UnsupportedOperationException | IOException e) {
                    log.error("Set icon error: ", e);
                }
            });
    }

    private static Optional<InputStream> getIconStream() {
        return Optional.ofNullable(ClassLoader.getSystemResourceAsStream(CommonConstants.APP_ICON));
    }

    private static void loadConfig() throws IOException {
        // 重启不需要加载
        if (Objects.isNull(ConfigContext.get())) {
            ConfigContext.load();
        }
        if (MapUtils.isEmpty(PluginConfigurationContext.getAll())) {
            PluginConfigurationContext.load();
        }
    }
}
